﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using Kugar.Core.ExtMethod;
using Kugar.UI.Web.AdminLTE.Enums;
using Kugar.UI.Web.AdminLTE.Helpers;
using Kugar.UI.Web.AdminLTE.PageControls.Helpers.ButtonExtMethod;
using Kugar.UI.Web.AdminLTE.PageControls.PageForms;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc.Rendering;
using Newtonsoft.Json.Linq;

namespace Kugar.UI.Web.AdminLTE.PageControls.PageCommon
{
    public class PageCommon_QueryBox:ControlBase
    {
        private int _colQty = 4;
        private List<AdminLTEElementBase> _items=new List<AdminLTEElementBase>();
        private Lazy<List<(string name,string value)>> _hiddenValues=new Lazy<List<(string name, string value)>>();
        private string _buttonText = "查询";
        private string _buttonIconCss = "fa-search";
        private ColorPaletteEnum _buttonColor = ColorPaletteEnum.info;
        private string _url = "";
        private string _method = "get";
        private bool _isAjax = false;
        private string _updateElementID = "";
        private string _formID = "";
        private bool _hideQueryButton = true;
        internal bool _horizontal = true;


        public PageCommon_QueryBox(ViewContext viewContext) : base(viewContext)
        {
            this.Css("querybox");
        }

        /// <summary>
        /// 每行多少个查询条件框,默认为4个,,只能是: 2,3,4,6 选一种
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public PageCommon_QueryBox ColQty(QueryBoxColCount count)
        {
            _colQty = (int)count;

            return this;
        }

        public PageCommon_QueryBox QueryButtonText(string buttonText)
        {
            _buttonText = buttonText;

            return this;
        }

        public PageCommon_QueryBox QueryButtonColor(ColorPaletteEnum color)
        {
            _buttonColor = color;

            return this;
        }

        public PageCommon_QueryBox QueryButtonIconCss(string iconCss)
        {
            _buttonIconCss = iconCss;

            return this;
        }

        [Obsolete("使用Get/Post函数")]
        public PageCommon_QueryBox Url(string queryUrl)
        {
            _url = queryUrl;
            return this;
        }

        [Obsolete("使用Get/Post函数")]
        public PageCommon_QueryBox Method(string method)
        {
            _method = method;
            return this;
        }

        public PageCommon_QueryBox Post(string url="")
        {
            _method = "post";
            _url = url;
            return this;
        }

        public PageCommon_QueryBox Get(string url="")
        {
            _method = "get";
            _url = url;
            return this;
        }

        /// <summary>
        /// 使用ajax的方式提交查询,并将结果替换掉指定id的元素,一般是modal的id或者form的id
        /// </summary>
        /// <param name="elementID"></param>
        /// <returns></returns>
        public PageCommon_QueryBox UpdateElementID(string elementID)
        {
            if (string.IsNullOrWhiteSpace(elementID))
            {
                throw new ArgumentNullException(nameof(elementID));
            }

            _updateElementID = elementID;
            _isAjax = true;

            return this;
        }

        public PageCommon_QueryBox FormID(string formID)
        {
            _formID = formID;

            return this;
        }

        /// <summary>
        /// 隐藏自带的查询按钮
        /// </summary>
        /// <param name="hide"></param>
        /// <returns></returns>
        public PageCommon_QueryBox HideQueryButton(bool hide = true)
        {
            _hideQueryButton = hide;

            return this;
        }

        /// <summary>
        /// 添加一个自定义字段
        /// </summary>
        /// <param name="item"></param>
        public void AddQueryItem(QueryBox_ItemBase item)
        {
            _items.Add(item);
        }



        public List<(string name, string value)> HiddenValues => _hiddenValues.Value;

        /// <summary>
        /// 插入一个提交按钮
        /// </summary>
        /// <param name="btn"></param>
        /// <returns></returns>
        public PageCommon_QueryBox AddSubmitButton()
        {
            return AddButton(x => x.Css("btn queryboxbutton")
                .Type(ButtonTypeEnum.submit)
                .Color(ColorPaletteEnum.primary)
                .Text("查询"));
        }

        /// <summary>
        /// 插入一个提交按钮
        /// </summary>
        /// <param name="btn"></param>
        /// <returns></returns>
        [Obsolete("请使用AddSubmitButton函数")]
        public PageCommon_QueryBox AddButton()
        {
            return AddSubmitButton();
        }

        /// <summary>
        /// 插入一个按钮
        /// </summary>
        /// <returns></returns>
        public PageCommon_QueryBox AddButton(Action<ButtonConfigBase> btn)
        {
            var config=new ButtonConfigBase(ViewContext);
            config.Css("btn queryboxbutton");
            config.Type(ButtonTypeEnum.submit)
                //.Color(ColorPaletteEnum.primary)
                //.Text("查询")
                ;
            
            btn(config);

            _items.Add(config);

            return this;
        }

        public override HtmlString Render()
        {
            this.Css("querybox_" + _colQty);

            if (_withOuterBorder)
            {
                ViewContext.Writer.WriteLine($"<div class=\"{_outerBorderCss}\">");
            }

            ViewContext.Writer.WriteLine($"<div {Attributes}>");

            if (string.IsNullOrWhiteSpace(_url))
            {
                _url = ViewContext.HttpContext.Request.GetDisplayUrl();
            }

            var count = (int) ViewContext.TempData.TryGetValue("FormCount", 0);


            ViewContext.Writer.WriteLine($"<{(count>0?"div":"form")} {(count>0?"data-innerform=\"True\"":"")} role=\"form\" {_formID.IfNotEmptyOrWhileSpace($"id=\"{_formID}\"")} {(_isAjax.If("data-ajax=\"True\""))} {_updateElementID.IfNotEmptyOrWhileSpace(x=>$"data-updateelemid=\"{x}\"")} class=\"queryboxform weui-form_formcontainer layui-form\"  action=\"{_url}\" method=\"{_method}\">");

            if (_hiddenValues.IsValueCreated)
            {
                foreach (var v in _hiddenValues.Value)
                {
                    ViewContext.Writer.WriteLine($"<input type=\"hidden\" name=\"{v.name}\" value=\"{v.value}\" />");
                }
            }
            

            ViewContext.Writer.WriteLine($"<div class=\"querycondition {(_horizontal? "horizontal":"")} {(_hideQueryButton ? " width-full" : "")}\">");

            for (int i = 0; i < _items.Count; i++)
            {
                if (_items[i] is QueryBox_ItemBase)
                {
                    (_items[i] as QueryBox_ItemBase).Render();

                    if ((i + 1) % _colQty == 0)
                    {
                        ViewContext.Writer.WriteLine("<div class=\"clearfix\"></div>");
                    }
                }
                else if(_items[i] is ButtonConfigBase)
                {
                    var btnConfig= (_items[i] as ButtonConfigBase);

                    if (btnConfig._hide)
                    {
                        continue;
                    }


                    btnConfig.Command?.RenderToButton(btnConfig);

                    btnConfig.Css("btn-" + btnConfig.GetColor);

                    ViewContext.Writer.WriteLine($"<{btnConfig.ReommentTag} {btnConfig.Attributes}>{btnConfig._iconHtml}{btnConfig.GetText}</{btnConfig.ReommentTag}>");
                }
                

                
            }

            if ((_items.Count % _colQty) !=0)
            {
                ViewContext.Writer.WriteLine("<div class=\"clearfix\"></div>");
            }
            

            ViewContext.Writer.WriteLine("</div> <!-- .querycondition -->");

            if (!_hideQueryButton)
            {
                var btnAttr = new TagAttrbute();
                btnAttr.Class("btn btn-" + _buttonColor.ToStringEx());

                var iconHtml = "";
                if (!string.IsNullOrWhiteSpace(_buttonIconCss))
                {
                    iconHtml = $"<i class=\"fa {_buttonIconCss}\"></i>";
                }

                ViewContext.Writer.WriteLine($"<div class=\"querybuttonarea\"><button type=\"submit\" {btnAttr}>{iconHtml}{_buttonText}</button></div>");
            }
            
            ViewContext.Writer.WriteLine("<div class=\"clearfix\"></div>");

            ViewContext.Writer.WriteLine($"</{(count>0?"div":"form")}>");

            ViewContext.Writer.WriteLine("</div> <!-- .querybox -->");

            if (_withOuterBorder)
            {
                ViewContext.Writer.WriteLine($"</div> <!-- outer border -->");
            }

            return HtmlString.Empty;
        }

        #region 查询条件框

        /// <summary>
        /// 查询子条件框的基类
        /// </summary>
        public abstract class QueryBox_ItemBase:AdminLTEElementBase
        {
            internal string _label = "";
            protected PageCommon_QueryBox _box = null;
            internal int _colQty = 3;
            internal Lazy<List<(string name,string value)>> _hiddenValues=new Lazy<List<(string name, string value)>>();

            protected QueryBox_ItemBase(PageCommon_QueryBox box, ViewContext viewContext) : base(viewContext)
            {
                _box = box;

                this.Css($"form-group queryboxitem_itemcondition");

                
            }

            internal void Render()
            {
                /*
                 <div class="form-group col-xs-3">
                    <label>Text</label>
                    <input type="text" class="form-control" placeholder="Enter ...">
                </div>
                 */

                BeforeRender(ViewContext.Writer);

                ViewContext.Writer.WriteLine($"<div {Attributes}>");

                if (!string.IsNullOrWhiteSpace(_label))
                {
                    ViewContext.Writer.WriteLine($"<label class=\"queryitemtitle {(_box._horizontal?"col-sm-" + _colQty:"")}\">{_label}</label>");
                }

                ViewContext.Writer.WriteLine($"<div class=\"querycontent {(_box._horizontal ? "col-sm-" + (12-_colQty) : "")}\" >");

                BeforeRenderContent(ViewContext.Writer);

                RenderContent(ViewContext.Writer);

                if (_hiddenValues.IsValueCreated)
                {
                    foreach (var pair in _hiddenValues.Value)
                    {
                        ViewContext.Writer.WriteLine($"<input type=\"hidden\" name=\"{pair.name}\" value=\"{pair.value}\" />");
                    }
                }

                AfterRenderContent(ViewContext.Writer);

                ViewContext.Writer.WriteLine("</div>");

                ViewContext.Writer.WriteLine("</div>");

                AfterRender(ViewContext.Writer);
            }

            protected abstract void RenderContent(TextWriter writer);

            protected virtual void BeforeRender(TextWriter writer) { }

            protected virtual void AfterRender(TextWriter writer) { }

            protected virtual void BeforeRenderContent(TextWriter writer) { }

            protected virtual void AfterRenderContent(TextWriter writer) { }

            public List<(string name, string value)> HiddenValues => _hiddenValues.Value;
        }

        public class QueryBox_TextBox : QueryBox_ItemBase
        {
            private string _placeholder = "";
            private string _value = "";
            private string _name = "";
            private int _length = -1;
            private bool _isAutoSelect = false;

            public QueryBox_TextBox(PageCommon_QueryBox box, ViewContext viewContext) : base(box, viewContext)
            {
                this.Css("queryboxitem_textbox");
            }

            public QueryBox_TextBox PlaceHolder(string placeholder)
            {
                _placeholder = placeholder;

                return this;
            }

            public QueryBox_TextBox Value(string value)
            {
                _value = value;

                return this;
            }

            public QueryBox_TextBox MaxLength(int length)
            {
                _length = length;

                return this;
            }

            public QueryBox_TextBox Name(string name)
            {
                _name = name;
                return this;
            }

            public QueryBox_TextBox SelectedOnClick(bool isAutoSelect=true)
            {
                _isAutoSelect = isAutoSelect;

                return this;
            }

            protected override void RenderContent(TextWriter writer)
            {
                writer.WriteLine($"<input data-autoselected=\"{_isAutoSelect}\" type=\"text\" class=\"form-control\" {(_length>0?$"maxlength=\"{_length}\"":"")} name=\"{_name}\" value=\"{_value}\" placeholder=\"{_placeholder}\">");
            }

        }

        public class QueryBox_ValueRange : QueryBox_ItemBase
        {
            private string _startName = "";
            private string _endName = "";
            private string _startValue = "";
            private string _endValue = "";
            private string _maxValue = "";
            private string _minValue = "";
            private string _startPlaceHolder = "";
            private string _endPlaceHolder = "";
            private InputElementType _type = InputElementType.text;
            private bool _isAutoSelect = false;

            public QueryBox_ValueRange(PageCommon_QueryBox box, ViewContext viewContext) : base(box, viewContext)
            {
                this.Css("queryboxitem_valuerange");
            }

            public QueryBox_ValueRange Name(string startName, string endName)
            {
                _startName = startName;
                _endName = endName;
                return this;
            }

            public QueryBox_ValueRange Value(string startValue, string endValue)
            {
                _startValue = startValue;
                _endValue = endValue;

                return this;
            }

            public QueryBox_ValueRange ValueLimit(int maxValue, int minValue)
            {
                _maxValue = maxValue.ToStringEx();
                _minValue = minValue.ToString();

                return this;
            }

            public QueryBox_ValueRange Type(InputElementType type)
            {
                _type = type;

                return this;
            }

            public QueryBox_ValueRange SelectedOnClick(bool isAutoSelect = true)
            {
                _isAutoSelect = isAutoSelect;

                return this;
            }

            public QueryBox_ValueRange Placeholder(string startValuePlaceholder, string endPlaceholder)
            {
                _startPlaceHolder = startValuePlaceholder;
                _endPlaceHolder = endPlaceholder;

                return this;
            }

            protected override void RenderContent(TextWriter writer)
            {
                /*
                 <div class="input-valuerange input-group">
                    <input type="text" class="input-group form-control startvalue" name="StartDt" value="" placeholder="下单时间">
                    <span class="input-group-addon">-</span>
                    <input type="text" class="input-group form-control endvalue" name="EndDt" value="" placeholder="下单时间">
                    <!-- End input-daterange -->
                </div>
                 */

                ViewContext.Writer.WriteLine("<div class=\"input-valuerange input-group\">");

                ViewContext.Writer.WriteLine($"<input type=\"{_type}\" name=\"{_startName}\" data-autoselected=\"{_isAutoSelect}\" value=\"{_startValue}\" max=\"{_maxValue}\" min=\"{_minValue}\" class=\"form-control\" placeholder=\"{_startPlaceHolder}\">");
                ViewContext.Writer.WriteLine("<span class=\"input-group-addon\">-</span>");
                ViewContext.Writer.WriteLine($"<input type=\"{_type}\" name=\"{_endName}\" data-autoselected=\"{_isAutoSelect}\" value=\"{_endValue}\" max=\"{_maxValue}\" min=\"{_minValue}\" class=\"form-control\" placeholder=\"{_endPlaceHolder}\">");

                ViewContext.Writer.WriteLine("</div>");
            }

        }

        public class QueryBox_TextBoxWithButton : QueryBox_ItemBase, ICommandElement
        {
            private string _placeholder = "";
            private string _value = "";
            private string _name = "";
            private int _length = -1;
            private ColorPaletteEnum _color = ColorPaletteEnum.info;
            private string _iconCss = "fa-search";
            private bool _isAutoSelect = false;
            private bool _readonly = false;
            private ButtonTypeEnum _buttonType = ButtonTypeEnum.button;
            private string _btnText = "";
            private bool _isHideBtnIcon;
            private InputElementType _inputType= InputElementType.text;

            public QueryBox_TextBoxWithButton(PageCommon_QueryBox box, ViewContext viewContext) : base(box, viewContext)
            {
            }

            public QueryBox_TextBoxWithButton PlaceHolder(string placeholder)
            {
                _placeholder = placeholder;

                return this;
            }

            public QueryBox_TextBoxWithButton Value(string value)
            {
                _value = value;

                return this;
            }

            public QueryBox_TextBoxWithButton MaxLength(int length)
            {
                _length = length;

                return this;
            }

            public QueryBox_TextBoxWithButton Name(string name)
            {
                _name = name;
                return this;
            }

            /// <summary>
            /// 隐藏按钮的前缀图标
            /// </summary>
            /// <param name="isHideIcon"></param>
            /// <returns></returns>
            public QueryBox_TextBoxWithButton HideButtonIcon(bool isHideIcon = true)
            {
                _isHideBtnIcon = isHideIcon;
                return this;
            }

            /// <summary>
            /// 是否点击文本框后自动选中文本框内的文本
            /// </summary>
            /// <param name="isAutoSelect"></param>
            /// <returns></returns>
            public QueryBox_TextBoxWithButton SelectedOnClick(bool isAutoSelect = true)
            {
                _isAutoSelect = isAutoSelect;

                return this;
            }

            public QueryBox_TextBoxWithButton InputType(InputElementType type)
            {
                _inputType = type;

                return this;
            }

            /// <summary>
            /// 是否为只读
            /// </summary>
            /// <param name="isReadOnly"></param>
            /// <returns></returns>
            public QueryBox_TextBoxWithButton ReadOnly(bool isReadOnly = true)
            {
                _readonly = isReadOnly;

                return this;
            }

            public QueryBox_TextBoxWithButton ButtonType(ButtonTypeEnum type)
            {
                if (type== ButtonTypeEnum.link)
                {
                    type = ButtonTypeEnum.button;
                }
                _buttonType = type;
                return this;
            }

            public QueryBox_TextBoxWithButton ButtonText(string btnText)
            {
                _btnText = btnText;

                return this;
            }

            public QueryBox_TextBoxWithButton ButtonIconCss(string iconCss)
            {
                _iconCss = iconCss;

                return this;
            }

            public QueryBox_TextBoxWithButton ButtonColor(ColorPaletteEnum color)
            {
                _color = color;

                return this;
            }

            public ButtonCmdBase Command { set; get; }

            protected override void RenderContent(TextWriter writer)
            {
                /*
                 <div class="input-group row">
                    <input class="form-control" />
                    <span class="input-group-btn">
                        <button type="button" class="btn btn-info"><i class="fa fa-upload"></i></button>
                    </span>
                </div>
                 */
                ViewContext.Writer.WriteLine("<div class=\"input-group\">");

                ViewContext.Writer.WriteLine($"<input class=\"form-control\" placeholder=\"{_placeholder}\" {_readonly.If("readonly")} data-autoselected=\"{_isAutoSelect}\" {(_length>0).If($"maxlength=\"{_length}\"")} type=\"{_inputType}\" name=\"{_name}\" value=\"{_value}\"/>");
                ViewContext.Writer.WriteLine("<span class=\"input-group-btn\">");

                
                var btnAttr = new TagAttrbute();
                btnAttr.Class("btn btn-" + _color.ToStringEx());

                Command?.RenderToElement(btnAttr);

                var iconHtml = "";

                if (!_isHideBtnIcon)
                {
                    if (!string.IsNullOrWhiteSpace(_iconCss))
                    {
                        iconHtml = $"<i class=\"fa {_iconCss}\"></i>";
                    }
                }
                else
                {
                    iconHtml = "";
                }

                ViewContext.Writer.WriteLine($"<button type=\"{_buttonType}\" {btnAttr}>{iconHtml}{_btnText}</button>");
                ViewContext.Writer.WriteLine("</span>");

                ViewContext.Writer.WriteLine("</div>");
            }
        }

        public class QueryBox_DateTime : QueryBox_ItemBase
        {
            private DateTime? _value = null;
            private DateTime? _minDt = null;
            private DateTime? _maxDt = null;
            private DatetimePickerType _type = DatetimePickerType.Date;
            private string _format = "";
            private string _name = "";
            private string _placeholder = "";

            public QueryBox_DateTime(PageCommon_QueryBox box, ViewContext viewContext) : base(box, viewContext)
            {
                this.Css("queryboxitem_datetime datetimepicker");
            }

            public QueryBox_DateTime Format(string format)
            {
                _format = format;
                return this;
            }

            public QueryBox_DateTime Value(DateTime? value)
            {
                _value = value;

                return this;
            }

            public QueryBox_DateTime Name(string name)
            {
                _name = name;
                return this;
            }

            public QueryBox_DateTime PlaceHolder(string placeholder)
            {
                _placeholder = placeholder;

                return this;
            }

            public QueryBox_DateTime ValueLimit(DateTime? minValue = null, DateTime? maxValue = null)
            {
                _maxDt = maxValue;
                _minDt = minValue;

                return this;
            }

            public QueryBox_DateTime Type(DatetimePickerType type)
            {
                _type = type;

                return this;
            }

            protected override void BeforeRender(TextWriter writer)
            {
                if (_format == "")
                {
                    _format = Utility.GetDefaultDateFormat(_type);
                }

                if (_value.HasValue)
                {
                    if (_minDt.HasValue && _minDt.Value > _value.Value)
                    {
                        _value = _minDt.Value;
                    }

                    if (_maxDt.HasValue && _maxDt.Value < _value.Value)
                    {
                        _value = _maxDt.Value;
                    }
                }

                this.Data("format", _format)
                    .Data("pickertype", _type.ToString())
                    .Data("maxdt", _maxDt.ToStringEx(_format))
                    .Data("mindt", _minDt.ToStringEx(_format))
                    ;

                base.BeforeRender(writer);
            }

            protected override void RenderContent(TextWriter writer)
            {
                if (_format == "")
                {
                    _format = Utility.GetDefaultDateFormat(_type);
                }

                writer.WriteLine("<div class=\"input-group\">");
                writer.WriteLine($"<input type=\"text\"  autocomplete=\"off\" placeholder=\"{_placeholder}\" name=\"{_name}\" value=\"{_value.ToStringEx(_format)}\"  class=\"form-control\" />");

                writer.WriteLine($"<span class=\"input-group-btn\"><button type=\"button\" class=\"btn btn-info datetimepickershow\"><i class=\"fa fa-calendar\"></i></button></span>");
                writer.WriteLine("</div> <!-- .input-group -->");
            }
        }

        public class QueryBox_DateTimeRange : QueryBox_ItemBase
        {
            private string _startName = "";
            private string _endName = "";
            private DateTime? _startValue = null;
            private DateTime? _endValue = null;
            private DateTime? _maxValue = null;
            private DateTime? _minValue = null;
            //private string _placeholder = null;
            private string _startPlaceholder = "";
            private string _endPlaceholder = "";
            private string _format = "";
            private DatetimePickerType _type = DatetimePickerType.Date;
            private bool _isEditable = true;

            public QueryBox_DateTimeRange(PageCommon_QueryBox box, ViewContext viewContext) : base(box, viewContext)
            {
                this.Css("queryboxitem_datetimerange datetimerangepicker");
            }

            public QueryBox_DateTimeRange Format(string format)
            {
                _format = format;

                //Attributes.SetOrReplaceAttr("format", format);

                return this;
            }

            public QueryBox_DateTimeRange Type(DatetimePickerType type)
            {
                _type = type;

                //Attributes.SetOrReplaceAttr("data-pickertype", type.ToStringEx());

                return this;
            }

            public QueryBox_DateTimeRange Name(string preName)
            {
                _startName = preName + "_Start";
                _endName = preName + "_End";

                return this;
            }

            public QueryBox_DateTimeRange Name(string startValueName, string endValueName)
            {
                _startName = startValueName;
                _endName = endValueName;

                return this;
            }

            public QueryBox_DateTimeRange Value(DateTime? startValue = null, DateTime? endValue = null)
            {
                _startValue = startValue;
                _endValue = endValue;

                return this;
            }

            public QueryBox_DateTimeRange ValueLimit(DateTime? minValue = null, DateTime? maxValue = null)
            {
                _maxValue = maxValue;
                _minValue = minValue;

                return this;
            }

            public QueryBox_DateTimeRange Placeholder(string startDtPlaceholder, string endDtPlaceholder)
            {
                _startPlaceholder = startDtPlaceholder;
                _endPlaceholder = endDtPlaceholder;

                return this;
            }

            public QueryBox_DateTimeRange Editabled(bool isEditable = true)
            {
                _isEditable = isEditable;
                return this;
            }

            protected override void BeforeRender(TextWriter writer)
            {
                if (_format == "")
                {
                    _format = Utility.GetDefaultDateFormat(_type);
                }

                if (_startValue.HasValue && _endValue.HasValue && _startValue.Value > _endValue.Value)
                {
                    throw new ArgumentOutOfRangeException("StartDt");
                }

                if (_minValue.HasValue && _startValue.HasValue && _startValue < _minValue)
                {
                    _startValue = _minValue;
                }

                if (_maxValue.HasValue && _endValue.HasValue && _maxValue < _endValue)
                {
                    _endValue = _maxValue;
                }


                this.Data("pickertype", _type.ToStringEx());
                this.Data("format", _format);

                if (_maxValue.HasValue)
                {
                    this.Data("maxdt", _maxValue.ToStringEx(_format));
                }

                if (_minValue.HasValue)
                {
                    this.Data("mindt", _minValue.ToStringEx(_format));
                }

                this.Data("data-startdisabled", false.ToString());
                this.Data("data-enddisabled", false.ToString());

                base.BeforeRender(writer);
            }

            protected override void RenderContent(TextWriter writer)
            {
                /*
                 <div class="input-group">
                    <input type="text" class="input-group form-control startvalue" id="txtStartValue" name="StartDt" value="" placeholder="下单时间">
                    <span class="input-group-addon">-</span>
                    <input type="text" class="input-group form-control endvalue" id="txtEndValue" name="EndDt" value="" placeholder="下单时间">
                    <!-- End input-daterange -->
                </div>
                 */

                ViewContext.Writer.WriteLine("<div class=\"input-group\">");

                ViewContext.Writer.WriteLine($"<input type=\"text\"  autocomplete=\"off\" class=\"input-group form-control startvalue\" {(!_isEditable).If("readonly")} name=\"{_startName}\" value=\"{_startValue.ToStringEx(_format)}\" placeholder=\"{_startPlaceholder}\">");
                ViewContext.Writer.WriteLine("<span class=\"input-group-addon\">-</span>");
                ViewContext.Writer.WriteLine($"<input type=\"text\"  autocomplete=\"off\" class=\"input-group form-control endvalue\" {(!_isEditable).If("readonly")} name=\"{_endName}\" value=\"{_endValue.ToStringEx(_format)}\" placeholder=\"{_endPlaceholder}\">");

                ViewContext.Writer.WriteLine("</div> <!-- .input-group -->");

            }
        }

        public class QueryBox_Selector : QueryBox_ItemBase
        {
            private string _name = "";
            private IEnumerable<SelectorItem> _options = null;
            private SelectorItem _firstItem = null;
            private string _selectedValue = "";
            private string _onChangedScript = "";
            private bool _isAutoSubmit = false;

            public QueryBox_Selector(PageCommon_QueryBox box, ViewContext viewContext) : base(box, viewContext)
            {
                this.Css("queryboxitem_selector");
            }

            /// <summary>
            /// 设定当下拉框修改时,,是否自动提交,会在OnChangedScript之后提交数据
            /// </summary>
            /// <param name="isAutoSubmit"></param>
            /// <returns></returns>
            public QueryBox_Selector AutoSubmit(bool isAutoSubmit = true)
            {
                _isAutoSubmit = isAutoSubmit;
                return this;
            }

            public QueryBox_Selector Name(string name)
            {
                _name = name;

                return this;
            }

            /// <summary>
            /// 修改时,触发的事件处理语句
            /// </summary>
            /// <param name="changedScript"></param>
            /// <returns></returns>
            public QueryBox_Selector OnChangedScript(string changedScript)
            {
                _onChangedScript = changedScript;

                return this;
            }

            public QueryBox_Selector CurrentValue(string selectedValue)
            {
                _selectedValue = selectedValue;

                return this;
            }

            public QueryBox_Selector CurrentValue(int selectedValue)
            {
                _selectedValue = selectedValue.ToStringEx();

                return this;
            }

            public QueryBox_Selector Options(params (string title,string value)[] options)
            {
                _options = options.Select(x=>new SelectorItem(x.title,x.value));

                return this;
            }

            public QueryBox_Selector Options(params (string title, int value)[] options)
            {
                _options = options.Select(x => new SelectorItem(x.title, x.value.ToString()));

                return this;
            }

            public QueryBox_Selector Options(IEnumerable<SelectorItem> options)
            {
                _options = options;

                return this;
            }

            public QueryBox_Selector Options<TEnumableData>(IEnumerable<TEnumableData> optionsGetter, Func<TEnumableData, string> titleGetter, Func<TEnumableData, string> valueGetter, Func<TEnumableData, bool> disabledGetter = null)
            {
                _options = optionsGetter.Select(x => new SelectorItem(titleGetter(x), valueGetter(x), disabledGetter?.Invoke(x) ?? false));

                return this;
            }

            /// <summary>
            /// 选项列表,根据枚举类型
            /// </summary>
            /// <param name="enumType"></param>
            /// <returns></returns>
            public QueryBox_Selector Options(Type enumType, Func<SelectorItem, bool> disabledGetter = null)
            {
                if (!enumType.IsEnum)
                {
                    throw new ArrayTypeMismatchException("enumType参数类型必须为枚举类型");
                }

                _options = Utility.GetEnumTypeToSelectorItems(enumType);

                if (disabledGetter != null)
                {
                    foreach (var opt in _options)
                    {
                        opt.Disabled = disabledGetter(opt);
                    }
                }

                return this;
            }

            /// <summary>
            /// 在末尾增加一个选项
            /// </summary>
            /// <param name="title"></param>
            /// <param name="value"></param>
            /// <returns></returns>
            public QueryBox_Selector AppendOption(string title, string value)
            {
                _options = _options.Concat(new[] { new SelectorItem(title, value) });

                return this;
            }

            /// <summary>
            /// 额外真在Options首个备选项前的选项
            /// </summary>
            /// <param name="firstItem"></param>
            /// <returns></returns>
            public QueryBox_Selector FirstItem(SelectorItem firstItem)
            {
                _firstItem = firstItem;

                return this;
            }

            public QueryBox_Selector FirstItem(string title, string value)
            {
                _firstItem = new SelectorItem(title, value);

                return this;
            }

            protected override void RenderContent(TextWriter writer)
            {
                /*
                   <select layui-igone class="form-control" multiple>
                      <option>option 1</option>
                      <option>option 2</option>
                      <option>option 3</option>
                      <option>option 4</option>
                      <option>option 5</option>
                    </select>
                 */

                writer.WriteLine($"<select class=\"form-control\" {_isAutoSubmit.If("data-autosubmit=\"True\"")} data-onchanged='{HttpUtility.HtmlEncode(_onChangedScript)}' name=\"{_name}\" >");

                if (_firstItem != null)
                {
                    writer.WriteLine($"<option value=\"{_firstItem.Value}\" {_firstItem.Disabled.If("disabled")}>{_firstItem.Title}</option>");
                }

                if (_options!=null)
                {
                    foreach (var option in _options)
                    {
                        writer.WriteLine($"<option value=\"{option.Value}\" {(_selectedValue == option.Value ? "selected" : "")} {option.Disabled.If("disabled")}>{option.Title}</option>");
                    }
                }
                

                writer.WriteLine("</select>");
            }
        }

        public class QueryBox_MultipleSelector : QueryBox_ItemBase
        {
            private string _name = String.Empty;
            private IEnumerable<SelectorItem> _options = null;
            private SelectorItem _firstItem = null;
            private string[] _selectedValue =null;
            private string _onChangedScript = "";
            private bool _isMultiSelect = false;
            private string _placeholder = String.Empty;
            private bool _isAutoSubmit = false;
            private int _maxSelectSize = -1;

            public QueryBox_MultipleSelector(PageCommon_QueryBox box, ViewContext viewContext) : base(box, viewContext)
            {
                this.Css("queryboxitem_multipleselect");
            }

            /// <summary>
            /// 最多可选的数量
            /// </summary>
            /// <param name="selectSize"></param>
            /// <returns></returns>
            public QueryBox_MultipleSelector MaxSelectionSize(int selectSize)
            {
                _maxSelectSize = selectSize;

                return this;
            }

            public QueryBox_MultipleSelector Name(string name)
            {
                _name = name;

                return this;
            }

            /// <summary>
            /// 设定当下拉框修改时,,是否自动提交,会在OnChangedScript之后提交数据
            /// </summary>
            /// <param name="isAutoSubmit"></param>
            /// <returns></returns>
            public QueryBox_MultipleSelector AutoSubmit(bool isAutoSubmit = true)
            {
                _isAutoSubmit = isAutoSubmit;
                return this;
            }

            /// <summary>
            /// 修改时,触发的事件处理语句
            /// </summary>
            /// <param name="changedScript"></param>
            /// <returns></returns>
            public QueryBox_MultipleSelector OnChangedScript(string changedScript)
            {
                _onChangedScript = changedScript;

                return this;
            }

            public QueryBox_MultipleSelector CurrentValue(string[] selectedValue)
            {
                _selectedValue = selectedValue;

                return this;
            }

            public QueryBox_MultipleSelector CurrentValue(int[] selectedValue)
            {
                _selectedValue = selectedValue.Select(x=>x.ToStringEx()).ToArrayEx();

                return this;
            }

            public QueryBox_MultipleSelector Options(IEnumerable<SelectorItem> options)
            {
                _options = options;

                return this;
            }

            public QueryBox_MultipleSelector Options<TEnumableData>(IEnumerable<TEnumableData> optionsGetter, Func<TEnumableData, string> titleGetter, Func<TEnumableData, string> valueGetter, Func<TEnumableData, bool> disabledGetter = null)
            {
                _options = optionsGetter.Select(x => new SelectorItem(titleGetter(x), valueGetter(x), disabledGetter?.Invoke(x) ?? false));

                return this;
            }

            /// <summary>
            /// 选项列表,根据枚举类型
            /// </summary>
            /// <param name="enumType"></param>
            /// <returns></returns>
            public QueryBox_MultipleSelector Options(Type enumType, Func<SelectorItem, bool> disabledGetter = null)
            {
                if (!enumType.IsEnum)
                {
                    throw new ArrayTypeMismatchException("enumType参数类型必须为枚举类型");
                }

                _options = Utility.GetEnumTypeToSelectorItems(enumType);

                if (disabledGetter != null)
                {
                    foreach (var opt in _options)
                    {
                        opt.Disabled = disabledGetter(opt);
                    }
                }

                return this;
            }

            public QueryBox_MultipleSelector Placeholder(string placeholder)
            {
                _placeholder = placeholder;

                return this;
            }

            /// <summary>
            /// 额外真在Options首个备选项前的选项
            /// </summary>
            /// <param name="firstItem"></param>
            /// <returns></returns>
            public QueryBox_MultipleSelector FirstItem(SelectorItem firstItem)
            {
                _firstItem = firstItem;

                return this;
            }

            public QueryBox_MultipleSelector FirstItem(string title, string value)
            {
                _firstItem = new SelectorItem(title, value);

                return this;
            }
            
            protected override void RenderContent(TextWriter writer)
            {
                /*
                   <select layui-igone class="form-control" multiple>
                      <option>option 1</option>
                      <option>option 2</option>
                      <option>option 3</option>
                      <option>option 4</option>
                      <option>option 5</option>
                    </select>
                 */

                writer.WriteLine($"<select class=\"form-control\" {_isAutoSubmit.If("data-autosubmit=\"True\"")} multiple data-placeholder=\"{_placeholder}\" data-maxselectionsize=\"{_maxSelectSize}\" onchanged='{_onChangedScript}' name=\"{_name}\" >");

                if (_firstItem != null)
                {
                    writer.WriteLine($"<option value=\"{_firstItem.Value}\" {_firstItem.Disabled.If("disabled")}>{_firstItem.Title}</option>");
                }

                foreach (var option in _options)
                {
                    writer.WriteLine($"<option value=\"{option.Value}\" {_selectedValue?.Contains(option.Value).If("selected")} {option.Disabled.If("disabled")}>{option.Title}</option>");
                }

                writer.WriteLine("</select>");
            }
            
        }

        public class QueryBox_Checkbox:QueryBox_ItemBase
        {
            private string[] _checkedValues = null;
            private SelectorItem[] _options = null;
            private bool _disabled = false;
            private string _name = "";
            private bool _autoSubmit = false;

            public QueryBox_Checkbox(PageCommon_QueryBox box, ViewContext viewContext) : base(box,viewContext)
            {
                this.Css("queryboxitem_checkboxlist");
            }

            public QueryBox_Checkbox Name(string name)
            {
                _name = name;

                return this;
            }

            public QueryBox_Checkbox Checked(string[] checkedValues)
            {
                _checkedValues = checkedValues;

                return this;
            }

            public QueryBox_Checkbox Options(IEnumerable<SelectorItem> options)
            {
                _options = options.ToArrayEx();

                return this;
            }

            public QueryBox_Checkbox Options<TData>(IEnumerable<TData> values, Func<TData, string> titleGetter,
                Func<TData, string> valueGetter, Func<TData, bool> disabledStateGetter = null)
            {
                _options = values.Select(x => new SelectorItem(titleGetter(x), valueGetter(x), disabledStateGetter?.Invoke(x) ?? false))
                    .ToArrayEx();

                return this;
            }

            /// <summary>
            /// 选项列表,根据枚举类型
            /// </summary>
            /// <param name="enumType"></param>
            /// <returns></returns>
            public QueryBox_Checkbox Options(Type enumType, Func<SelectorItem, bool> disabledGetter = null)
            {
                if (!enumType.IsEnum)
                {
                    throw new ArrayTypeMismatchException("enumType参数类型必须为枚举类型");
                }

                //var names = enumType.GetEnumNames();
                //var values = (int[])enumType.GetEnumValues();

                //var lst = new List<SelectorItem>(names.Length);

                //for (int i = 0; i < names.Length; i++)
                //{
                //    FieldInfo enumInfo = enumType.GetField(names[i]);

                //    var a = (DescriptionAttribute)enumInfo.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault();

                //    var k = new SelectorItem(a != null ? a.Description : names[i].ToStringEx(), values[i].ToString(), disabledGetter?.Invoke(values[i].ToString()) ?? false);

                //    lst.Add(k);
                //}

                //_options = lst.ToArrayEx();

                _options = Utility.GetEnumTypeToSelectorItems(enumType);

                if (disabledGetter != null)
                {
                    foreach (var opt in _options)
                    {
                        opt.Disabled = disabledGetter(opt);
                    }
                }

                return this;
            }

            public QueryBox_Checkbox AutoSubmit(bool autoSubmit = true)
            {
                _autoSubmit = autoSubmit;

                return this;
            }

            protected override void RenderContent(TextWriter writer)
            {
                foreach (var option in _options)
                {
                    writer.WriteLine($"<input type=\"checkbox\" {_checkedValues.Contains(option.Value).If("checked")} name=\"{_name}\" title=\"{option.Title}\" value=\"{option.Value}\" {(_disabled || option.Disabled).If("disabled")} lay-skin=\"primary\">");
                }
            }
        }

        public class QueryBox_TreeSelector: QueryBox_ItemBase
        {
            private PageCommon_Tree _tree = null;
            private string _name = "";
            private IEnumerable<string> _values = null;

            public QueryBox_TreeSelector(PageCommon_QueryBox box, ViewContext viewContext) : base(box, viewContext)
            {
                _tree=new PageCommon_Tree(viewContext);
                _tree.Css("dropdown-menu dropdown-treeview-menu-container");
                this.Css("webui-form_treeviewselectorfield");
            }

            public QueryBox_TreeSelector MaxLevel(int level)
            {
                _tree.MaxLevel(level);
                return this;
            }

            /// <summary>
            ///  顶级根节点列表
            /// </summary>
            /// <param name="source"></param>
            /// <returns></returns>
            public QueryBox_TreeSelector Root(IEnumerable<SelectorItem> source)
            {
                _tree.Root(source);
                return this;
            }

            public QueryBox_TreeSelector Root(IEnumerable<(string title, string value)> source)
            {
                _tree.Root(source);

                return this;
            }

            public QueryBox_TreeSelector Root(SelectorItem source)
            {
                _tree.Root(source);

                return this;
            }

            public QueryBox_TreeSelector Root((string title, string value) source)
            {
                _tree.Root(source);

                return this;
            }

            public QueryBox_TreeSelector Children(Func<SelectorItem, IEnumerable<SelectorItem>> childrenFunc)
            {
                _tree.Children(childrenFunc);

                return this;
            }

            public QueryBox_TreeSelector Children(Func<SelectorItem, IEnumerable<(string title, string value)>> childrenFunc)
            {
                _tree.Children(childrenFunc);

                return this;
            }

            public QueryBox_TreeSelector Name(string name)
            {
                _name = name;

                return this;
            }

            /// <summary>
            /// 需要选中的项的Value值,区分大小写
            /// </summary>
            /// <param name="values"></param>
            /// <returns></returns>
            public QueryBox_TreeSelector SelectedValues(IEnumerable<string> values)
            {
                _values = values;
                _tree.SelectedValues(values);

                return this;
            }

            /// <summary>
            /// 选中的节点Value值(单个)
            /// </summary>
            /// <param name="values"></param>
            /// <returns></returns>
            public QueryBox_TreeSelector SelectedValues(string values)
            {
                _values = new[] {values};
                _tree.SelectedValues(values);

                return this;
            }

            public QueryBox_TreeSelector OnChangedScript(string onChangedChanged)
            {
                _tree.OnChangedScript(onChangedChanged);

                return this;
            }

            public QueryBox_TreeSelector MultiSelect(bool isMultiSelect = true)
            {
                _tree.MultiSelect(isMultiSelect);

                return this;
            }

            protected override void RenderContent(TextWriter writer)
            {
                /*
                 <div class="input-group row">
                    <input class="form-control" />
                    <span class="input-group-btn">
                        <button type="button" class="btn btn-info"><i class="fa fa-upload"></i></button>
                    </span>
                </div>
                 */

                writer.WriteLine("<div class=\"input-group dropdown-treeview-container\">");

                writer.WriteLine("<label class=\"form-control\"><span class=\"title\"></span></label>");
                writer.WriteLine("<span class=\"input-group-btn dropdown-treeview-buttongroup\">\r\n<button type=\"button\" class=\"btn btn-success dropdown-toggle\" data-toggle=\"dropdown\" aria-expanded=\"true\">\r\n<span class=\"fa fa-caret-down\"></span>\r\n</button>\r\n</span>");
                writer.WriteLine($"<input type=\"hidden\" name=\"{_name}\" value=\"{_values.JoinToString()}\">");

                writer.WriteLine(_tree.Render().ToString());
                writer.WriteLine("</div> <!-- .dropdown-treeview-container -->");


                //writer.WriteLine("<div class=\"input-group dropdown-treeview-container\">");
                //writer.WriteLine("<label class=\"form-control\"><span class=\"title\"></span></label>");
                //writer.WriteLine("<span class=\"input-group-btn dropdown-treeview-buttongroup\">\r\n<button type=\"button\" class=\"btn btn-success dropdown-toggle\" data-toggle=\"dropdown\" aria-expanded=\"true\">\r\n<span class=\"fa fa-caret-down\"></span>\r\n</button>\r\n</span>");

                //writer.WriteLine($"<input type=\"hidden\" name=\"{_name}\" value=\"{_values.JoinToString()}\">");

                //writer.WriteLine(_tree.Render().ToString());

                //writer.WriteLine("</div> <!-- .dropdown-treeview-container -->");
            }

        }

        public class QueryBox_Button: PageCommon_Button
        {
            public QueryBox_Button(ViewContext viewContext) : base(viewContext)
            {
            }
            
        }

        #endregion

        #region 添加控件

        /// <summary>
        /// 添加一个文本框
        /// </summary>
        /// <param name="configfunc"></param>
        /// <returns></returns>
        public PageCommon_QueryBox AddTextBox(Action<QueryBox_TextBox> configfunc)
        {
            var s = new QueryBox_TextBox(this, this.ViewContext);

            configfunc(s);

            this.AddQueryItem(s);

            return this;
        }

        /// <summary>
        /// 添加一个文本框+按钮
        /// </summary>
        /// <param name="configfunc"></param>
        /// <returns></returns>
        public PageCommon_QueryBox AddTextBoxWithButton(Action<QueryBox_TextBoxWithButton> configfunc)
        {
            var s = new QueryBox_TextBoxWithButton(this, this.ViewContext);

            configfunc(s);

            this.AddQueryItem(s);

            return this;
        }
        
        /// <summary>
        /// 添加一个多选框,如果不多余2个选项可以使用该控件,如果多于2个,请使用MultipleSelector控件
        /// </summary>
        /// <param name="configfunc"></param>
        /// <returns></returns>
        public PageCommon_QueryBox AddCheckbox(Action<QueryBox_Checkbox> configfunc)
        {
            var s = new QueryBox_Checkbox(this, this.ViewContext);

            configfunc(s);

            this.AddQueryItem(s);

            return this;
        }

        /// <summary>
        /// 添加一个日期框
        /// </summary>
        /// <param name="configfunc"></param>
        /// <returns></returns>
        public PageCommon_QueryBox AddDateTime(Action<QueryBox_DateTime> configfunc)
        {
            var s = new QueryBox_DateTime(this, this.ViewContext);

            configfunc(s);

            this.AddQueryItem(s);

            return this;
        }

        /// <summary>
        /// 添加一个单选框
        /// </summary>
        /// <param name="configfunc"></param>
        /// <returns></returns>
        public PageCommon_QueryBox AddSelector(Action<QueryBox_Selector> configfunc)
        {
            var s = new QueryBox_Selector(this, this.ViewContext);

            configfunc(s);

            this.AddQueryItem(s);

            return this;
        }

        /// <summary>
        /// 添加一个日期范围选择框
        /// </summary>
        /// <param name="configfunc"></param>
        /// <returns></returns>
        public PageCommon_QueryBox AddDateTimeRange( Action<QueryBox_DateTimeRange> configfunc)
        {
            var s = new QueryBox_DateTimeRange(this, this.ViewContext);

            configfunc(s);

            this.AddQueryItem(s);

            return this;
        }

        /// <summary>
        /// 添加一个下拉多选框
        /// </summary>
        /// <param name="configfunc"></param>
        /// <returns></returns>
        public PageCommon_QueryBox AddMultipleSelector(Action<QueryBox_MultipleSelector> configfunc)
        {
            var s = new QueryBox_MultipleSelector(this, this.ViewContext);

            configfunc(s);

            this.AddQueryItem(s);

            return this;
        }

        /// <summary>
        /// 添加一个隐藏数值字段,使用hidden,查询框级别
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public PageCommon_QueryBox AddHiddenValue(string name, string value)
        {
            this.HiddenValues.Add((name, value));
            return this;
        }

        /// <summary>
        /// 添加一个值范围的控件
        /// </summary>
        /// <typeparam name="TQueryBox"></typeparam>
        /// <param name="querybox"></param>
        /// <param name="configfunc"></param>
        /// <returns></returns>
        public PageCommon_QueryBox AddValueRange(Action<QueryBox_ValueRange> configfunc)
        {
            var s = new QueryBox_ValueRange(this, this.ViewContext);

            configfunc(s);

            this.AddQueryItem(s);

            return this;
        }

        public PageCommon_QueryBox AddTreeSelector(Action<QueryBox_TreeSelector> configfunc)
        {
            var s = new QueryBox_TreeSelector(this, this.ViewContext);

            configfunc(s);

            this.AddQueryItem(s);

            return this;
        }

        #endregion
    }

    public static class QueryBoxExtHelper
    {
        public static TQueryBoxItem BoxItemLabel<TQueryBoxItem>(this TQueryBoxItem queryboxItem, string label) where TQueryBoxItem : PageCommon_QueryBox.QueryBox_ItemBase
        {
            queryboxItem._label = label;

            return queryboxItem;
        }

        public static TQueryBoxItem AddItemHiddenValue<TQueryBoxItem>(this TQueryBoxItem src, string name, string value)
            where TQueryBoxItem : PageCommon_QueryBox.QueryBox_ItemBase
        {
            src.HiddenValues.Add((name, value));

            return src;
        }

        /// <summary>
        /// 标题占用的比例col-sm-*
        /// </summary>
        /// <typeparam name="TQueryBoxItem"></typeparam>
        /// <param name="src"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static TQueryBoxItem LabelWidth<TQueryBoxItem>(this TQueryBoxItem src, int colQty=3)
            where TQueryBoxItem : PageCommon_QueryBox.QueryBox_ItemBase
        {
            src._colQty=colQty;

            return src;
        }

        /// <summary>
        /// 水平显示查询条件
        /// </summary>
        /// <returns></returns>
        public static TQueryBox Horizontal<TQueryBox>(this TQueryBox box, bool ishorizontal=true) where TQueryBox: PageCommon_QueryBox
        {
            box._horizontal = ishorizontal;

            return box;
        }
    }
}
